home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 July / macformat-026.iso / mac / Shareware City / Utilities / Reset DTDBs 2.1 Folder / Source / resetdtdbs.c next >
Encoding:
C/C++ Source or Header  |  1995-03-30  |  7.9 KB  |  314 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Reset DTDBs
  3.  *   Resets desktop databases of mounted volumes.
  4.  * 
  5.  * Source file: resetdtdbs.c
  6.  * Written by Brian Gaeke. E-mail: <brg@dgate.org>
  7.  * Created 28 December 1992.
  8.  * 
  9.  * The source code to Reset DTDBs is copyrighted © 1992, 1993, 1995 by The
  10.  * Dimensional Gate Company. All rights reserved worldwide except where
  11.  * specifically permitted.
  12.  * 
  13.  *   Source Notes (These were formerly distributed in a separate file.)
  14.  *
  15.  * Reset DTDBs is very, very simple--shows a few dialogs, calls a few Desktop Manager
  16.  * functions, and then restarts. If you are not familiar with the Desktop Manager, it
  17.  * would do you good to read pages 9-44 to 9-60 in Inside Macintosh VI before you
  18.  * read the source. The code simply cycles through the VCB and calls 
  19.  * PBDTCloseDown(), PBDTFlush(), and PBDTDelete() on each vRefNum in the VCB queue.
  20.  * The done() macro compares its argument to the qTail of the VCB queue, and then
  21.  * checks to see if there is only one mounted volume (as the case may be.) If these
  22.  * are both true, then the whole VCB has been scanned, and the loop stops.
  23.  * 
  24.  * The compiled program is now distributed with the source. I imagine (although I am
  25.  * not sure) that it could be ported to MPW C very easily. You are specifically
  26.  * permitted to use elements of the Reset DTDBs code in your programs, provided that
  27.  * you include the phrase "Portions copyright © 1992, 1993, 1995 by The Dimensional
  28.  * Gate Company" in your documentation and source code.
  29.  * 
  30.  * Version 2.1 (Mar. 30, 1995): Added a quickie preferences option that allows
  31.  * the user to set a "silent running" feature. When the opening dialog comes up the
  32.  * user can hit 'Quit, but don't prompt next time' - this will change a word in the
  33.  * resource fork of the application (a boo-boo stylistically, I know -- let it come
  34.  * back to bite me! then I'll work on adding findfolder support -- this is supposed
  35.  * to be simple) that will make reset dtdbs not prompt next time. Hold shift when
  36.  * starting to set this flag back to normal. This is a clunky interface, to be sure,
  37.  * but it will probably be replaced once I get around to making v3.0. (i.e. Never :)
  38.  */
  39.  
  40. #define done(vcb) ((vcb) == (vcbQHdr->qTail)) && ((vcbQHdr->qHead) != (vcbQHdr->qTail))
  41. #include <Processes.h>
  42. #include <AppleEvents.h>
  43. #include <ShutDown.h>
  44.  
  45. enum
  46. {
  47.     StartupAlrt = 128,
  48.     ConfirmAlrt = 129,
  49.     ErrorAlrt   = 130,
  50.     SuccessAlrt = 131,
  51.     ToggleAlrt  = 132,
  52.     PrefRsrcID  = 128
  53. };
  54.  
  55. #define PrefRsrcType 'Pref' 
  56. #define FinderSignature 'MACS'
  57. #define _TRUE_ 1
  58. #define _FALSE_ 0
  59.  
  60. typedef short bool;
  61.  
  62. /* 2.1 - Silent running states:  0 - not silent running, run like usual. 
  63.  *         (PrefsRec.silent)     1 - yes silent running, don't prompt.
  64.  */
  65. typedef struct PrefsRec
  66. {
  67.     bool silent;
  68. } PrefsRec, **PrefsRsrc;
  69.  
  70. PrefsRsrc prefs = NULL;
  71.  
  72. PrefsRsrc GetPrefs(void);
  73. void TurnSilentOff_ifShiftDown(void);
  74. void TurnSilentOn(void);
  75. pascal void main(void);
  76. short OpenDatabase(short vRefNum);
  77. void DeleteDatabase(short dtRefNum);
  78. void PrepareDatabase(short dtRefNum);
  79. void InitMac(void);
  80. void DoDialogs(void);
  81. void KillFinder(void);
  82. void Panic(OSErr err, unsigned char *routine);
  83.  
  84. PrefsRsrc GetPrefs(void)
  85. {
  86.     PrefsRsrc temp;
  87.     
  88.     temp = GetResource(PrefRsrcType,PrefRsrcID);
  89.     if (!temp)
  90.     {
  91.         if (ResError() == resNotFound)
  92.         {
  93.             temp = (PrefsRsrc) NewHandle(sizeof(PrefsRec));
  94.             if (!temp)
  95.                 Panic(MemError(),"\pAllocating mem. for new pref. data");
  96.             AddResource(temp,PrefRsrcType,PrefRsrcID,"\p");
  97.             if (ResError() != noErr)
  98.                 Panic(ResError(),"\pWriting new pref. data");
  99.         }
  100.         else
  101.             Panic(ResError(),"\pReading pref. data");
  102.     }
  103.     return temp;
  104. }
  105.  
  106. bool ShiftKeyDown(void)
  107. {
  108.     EventRecord event;
  109.     Boolean gotEvent;
  110.     
  111.     gotEvent = EventAvail(everyEvent,&event);
  112.     return ((event.modifiers & shiftKey) ? 1 : 0);
  113. }
  114.  
  115. void TurnSilentOff_ifShiftDown(void)
  116. {
  117.     /* We're sure we have a Pref resource now...I hope */
  118.     if (ShiftKeyDown())
  119.     {
  120.         ParamText("\p not",
  121.             "\pprompt you for confirmation before resetting, as usual.",
  122.             "\pclick the 'Quit & run silently next time' button on the startup dialog.",
  123.             "\p");
  124.         (void)Alert(ToggleAlrt,NULL);
  125.         (*prefs)->silent = _FALSE_;
  126.         ChangedResource(prefs);
  127.         if (ResError() != noErr)
  128.             Panic(ResError(),"\pWriting pref. data");
  129.         ExitToShell();
  130.     }
  131. }
  132.  
  133. void TurnSilentOn(void)
  134. {
  135.     /* We're sure we have a Pref resource now...I hope */
  136.     ParamText("\p",
  137.         "\pNOT prompt you for confirmation before resetting the databases, so that "
  138.             "it will run unattended.",
  139.         "\phold the Shift key as you start up Reset DTDBs.",
  140.         "\p");
  141.     (void)Alert(ToggleAlrt,NULL);
  142.     (*prefs)->silent = _TRUE_;
  143.     ChangedResource(prefs);
  144.     if (ResError() != noErr)
  145.         Panic(ResError(),"\pWriting pref. data");
  146.     ExitToShell();
  147. }
  148.  
  149. pascal void main(void)
  150. {
  151.     QHdrPtr        vcbQHdr = GetVCBQHdr();
  152.     VCB            *aVCB = (VCB *) vcbQHdr->qHead;
  153.     short        itsVRefNum,
  154.                 itsDTRefNum;
  155.     
  156.     InitMac();
  157.     
  158.     prefs = GetPrefs();
  159.     TurnSilentOff_ifShiftDown();
  160.     
  161.     if (!(*prefs)->silent)
  162.         DoDialogs();
  163.         
  164.     KillFinder();
  165.     while (!done(aVCB))
  166.     {
  167.         itsVRefNum = aVCB->vcbVRefNum;
  168.         itsDTRefNum = OpenDatabase(itsVRefNum);
  169.         PrepareDatabase(itsDTRefNum);
  170.         DeleteDatabase(itsVRefNum);
  171.         aVCB = (VCB *) aVCB->qLink;
  172.     };
  173.     
  174.     if (!(*prefs)->silent)
  175.         (void)Alert(SuccessAlrt,NULL);
  176.     ShutDwnStart();
  177. }
  178.  
  179. short OpenDatabase(short vRefNum)
  180. {
  181.     DTPBRec     dtpb;
  182.     short        dtRefNum;
  183.     OSErr        err;
  184.     
  185.     dtpb.ioCompletion = NULL;
  186.     dtpb.ioNamePtr = NULL;
  187.     dtpb.ioVRefNum = vRefNum;
  188.     err = PBDTGetPath(&dtpb);
  189.     if (err) Panic(err,"\pOpenDatabase");
  190.     return dtpb.ioDTRefNum;
  191. }
  192.  
  193. void DeleteDatabase(short vRefNum)
  194. {
  195.     DTPBRec        dtpb;
  196.     OSErr        err;
  197.     
  198.     dtpb.ioCompletion = NULL;
  199.     dtpb.ioVRefNum = vRefNum;
  200.     dtpb.ioIndex = 0;
  201.      err = PBDTDelete(&dtpb,false);
  202.     if (err) Panic(err,"\pDeleteDatabase");
  203. }
  204.  
  205. void PrepareDatabase(short dtRefNum)
  206. {
  207.     DTPBRec        dtpb;
  208.     OSErr        err;
  209.     
  210.     dtpb.ioCompletion = NULL;
  211.     dtpb.ioDTRefNum = dtRefNum;
  212.     err = PBDTFlush(&dtpb,false);
  213.     if (err) Panic(err,"\pPrepareDatabase--Flush");
  214.     
  215.     err = PBDTCloseDown(&dtpb);
  216.     if (err) Panic(err,"\pPrepareDatabase--CloseDown");
  217. }
  218.  
  219. void InitMac(void)
  220. {
  221.     short        x;
  222.     
  223.     InitGraf(&qd.thePort);
  224.     InitFonts();
  225.     FlushEvents(everyEvent,0);
  226.     InitWindows();
  227.     InitMenus();
  228.     TEInit();
  229.     InitDialogs(NULL);
  230.     InitCursor();
  231.     MaxApplZone();
  232.     for(x=1;x<11;x++)
  233.         MoreMasters();
  234. }
  235.  
  236. void DoDialogs(void)
  237. {
  238.     if (Alert(StartupAlrt,NULL) != ok) TurnSilentOn();
  239.     if (Alert(ConfirmAlrt,NULL) != ok) ExitToShell();
  240. }
  241.  
  242. void KillFinder(void)
  243. {
  244.     ProcessSerialNumber        psn,
  245.                             finder;
  246.     ProcessInfoRec            pir;
  247.     OSErr                    err;
  248.     AppleEvent                theEvent;
  249.     AEDesc                    theAddress;
  250.     Boolean                    gotEvent;
  251.     EventRecord                event;
  252.     short                    x;
  253.     
  254.     /* We have to do this because IM VI says not to call PBDTReset/PBDTDelete
  255.      * "unless you are manipulating the desktop database in the absence
  256.      * of the Finder"... and we all know that IM is the word of God... :)
  257.      * So here goes...
  258.      */
  259.        
  260.     psn.highLongOfPSN = 0;
  261.     psn.lowLongOfPSN = kNoProcess;
  262.     
  263.     pir.processInfoLength = sizeof(ProcessInfoRec);
  264.     pir.processAppSpec = NULL;
  265.     pir.processName = NULL;
  266.     
  267.     while (GetNextProcess(&psn) != procNotFound)
  268.     {
  269.         (void)GetProcessInformation(&psn,&pir);
  270.         if (pir.processSignature == FinderSignature)
  271.         {
  272.             finder = psn;
  273.             break;
  274.         }
  275.     }
  276.     
  277.     /*** kill the app code swiped from C.K. Haun with minimal modifications ***/
  278.     (void)AECreateDesc(typeProcessSerialNumber, (Ptr)&finder,
  279.       sizeof(finder), &theAddress);
  280.     (void)AECreateAppleEvent(kCoreEventClass, kAEQuitApplication,
  281.       &theAddress, kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
  282.     AEDisposeDesc(&theAddress);
  283.     AESend(&theEvent, NULL, kAENoReply + kAEAlwaysInteract +
  284.       kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  285.     AEDisposeDesc(&theEvent);
  286.     /*** end swiped code ***/
  287.     
  288.     /* give it time to work */
  289.     for(x=1; x<=5; x++)
  290.         gotEvent = EventAvail(everyEvent, &event);
  291.         
  292. }
  293.  
  294. void Panic(OSErr err, unsigned char *routine)
  295. {
  296.     Str255 errstr;
  297.     
  298.     if (prefs)
  299.     {
  300.         if (!(*prefs)->silent)
  301.         {
  302.             NumToString((long) err,errstr);
  303.             ParamText(errstr,routine,"\p","\p");
  304.             (void)Alert(ErrorAlrt,NULL);
  305.         }
  306.     }
  307.     else
  308.     {
  309.         SysBeep(1);
  310.     }
  311.     ShutDwnStart();
  312. }
  313.  
  314.